"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const vue_1 = require("vue");
const vdirs_1 = require("vdirs");
const treemate_1 = require("treemate");
const _internal_1 = require("../../_internal");
const utils_1 = require("./utils");
const interface_1 = require("./interface");
const utils_2 = require("../../select/src/utils");
exports.default = (0, vue_1.defineComponent)({
    name: 'NCascaderSelectMenu',
    props: {
        value: {
            type: [String, Number, Array],
            default: null
        },
        show: Boolean,
        pattern: {
            type: String,
            default: ''
        },
        multiple: Boolean,
        tmNodes: {
            type: Array,
            default: () => []
        },
        filter: Function,
        labelField: {
            type: String,
            required: true
        },
        separator: {
            type: String,
            required: true
        }
    },
    setup(props) {
        const { isMountedRef, mergedValueRef, mergedClsPrefixRef, mergedThemeRef, mergedCheckStrategyRef, syncSelectMenuPosition, closeMenu, handleSelectMenuClickOutside, doUncheck: cascaderDoUncheck, doCheck: cascaderDoCheck
        // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
         } = (0, vue_1.inject)(interface_1.cascaderInjectionKey);
        const menuInstRef = (0, vue_1.ref)(null);
        const selectOptionsRef = (0, vue_1.computed)(() => {
            return (0, utils_1.createSelectOptions)(props.tmNodes, mergedCheckStrategyRef.value === 'child', props.labelField, props.separator);
        });
        const mergedFilterRef = (0, vue_1.computed)(() => {
            const { filter } = props;
            if (filter)
                return filter;
            const { labelField } = props;
            return (pattern, _, path) => path.some((option) => option[labelField] && ~option[labelField].indexOf(pattern));
        });
        const filteredSelectOptionsRef = (0, vue_1.computed)(() => {
            const { pattern } = props;
            const { value: mergedFilter } = mergedFilterRef;
            return (pattern
                ? selectOptionsRef.value.filter((option) => {
                    return mergedFilter(pattern, option.rawNode, option.path);
                })
                : selectOptionsRef.value).map((option) => ({
                value: option.value,
                label: option.label
            }));
        });
        const selectTreeMateRef = (0, vue_1.computed)(() => {
            return (0, treemate_1.createTreeMate)(filteredSelectOptionsRef.value, utils_2.tmOptions);
        });
        (0, vue_1.watch)((0, vue_1.toRef)(props, 'value'), () => {
            void (0, vue_1.nextTick)(() => {
                syncSelectMenuPosition();
            });
        });
        (0, vue_1.watch)(filteredSelectOptionsRef, () => {
            void (0, vue_1.nextTick)(() => {
                syncSelectMenuPosition();
            });
        });
        function handleToggle(tmNode) {
            doCheck(tmNode);
        }
        // We don't care what type the tmNode is, we only care about its key
        function doCheck(tmNode) {
            if (props.multiple) {
                const { value: mergedValue } = mergedValueRef;
                if (Array.isArray(mergedValue)) {
                    if (!mergedValue.includes(tmNode.key)) {
                        cascaderDoCheck(tmNode.key);
                    }
                    else {
                        cascaderDoUncheck(tmNode.key);
                    }
                }
                else if (mergedValue === null) {
                    cascaderDoCheck(tmNode.key);
                }
            }
            else {
                cascaderDoCheck(tmNode.key);
                // currently the select menu is set to focusable
                // however just leave it here
                closeMenu(true);
            }
        }
        function prev() {
            var _a;
            (_a = menuInstRef.value) === null || _a === void 0 ? void 0 : _a.prev();
        }
        function next() {
            var _a;
            (_a = menuInstRef.value) === null || _a === void 0 ? void 0 : _a.next();
        }
        function enter() {
            var _a;
            if (menuInstRef) {
                const pendingOptionTmNode = (_a = menuInstRef.value) === null || _a === void 0 ? void 0 : _a.getPendingTmNode();
                if (pendingOptionTmNode) {
                    doCheck(pendingOptionTmNode);
                }
                return true;
            }
            return false;
        }
        function handleClickOutside(e) {
            handleSelectMenuClickOutside(e);
        }
        const exposedRef = {
            prev,
            next,
            enter
        };
        return Object.assign({ isMounted: isMountedRef, mergedTheme: mergedThemeRef, mergedClsPrefix: mergedClsPrefixRef, menuInstRef, selectTreeMate: selectTreeMateRef, handleToggle,
            handleClickOutside }, exposedRef);
    },
    render() {
        const { mergedClsPrefix, isMounted, mergedTheme } = this;
        return ((0, vue_1.h)(vue_1.Transition, { name: "fade-in-scale-up-transition", appear: isMounted }, {
            default: () => this.show
                ? (0, vue_1.withDirectives)((0, vue_1.h)(_internal_1.NInternalSelectMenu, { ref: "menuInstRef", clsPrefix: mergedClsPrefix, class: `${mergedClsPrefix}-cascader-menu`, autoPending: true, themeOverrides: mergedTheme.peerOverrides.InternalSelectMenu, theme: mergedTheme.peers.InternalSelectMenu, treeMate: this.selectTreeMate, multiple: this.multiple, value: this.value, onToggle: this.handleToggle }), [[vdirs_1.clickoutside, this.handleClickOutside]])
                : null
        }));
    }
});
